package com.edushare.common.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.query.SelectQuery;

import com.edushare.common.mailer.ExistingUserInvite;
import com.edushare.common.mailer.Invite;
import com.edushare.common.orm.ORMInterface;
import com.edushare.common.vo.UnivDeptLink;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.UserRoles;
import com.edushare.common.vo.Users;

public class UserRolesDAO extends CayenneBasedDAO {

	public UserRolesDAO(ORMInterface ormInterface) {
		super(ormInterface);
	}

	public List<Users> getUsersByRole(Universities univ, int role){
		List<UserRoles> rL = univ.getUserRoleList();
		List<Users> userList = new ArrayList<Users>();
		for(UserRoles r:rL){
			if(r.getRoleType() == role)
				userList.add(r.getUser());
		}
		return userList;
	}

	public UserRoles getRole(Universities univ, Users u) {
		List<UserRoles> rL = u.getRoleList();
		for(UserRoles r:rL){
			if(r.getUniversity() == univ){
				return r;
			}
		}
		return null;
	}

	public boolean isUserPresent(Universities univ, Users u) {
		if (getRole(univ, u) == null)
		return false;
		return true;
	}
	
	public boolean isUserAdmin(Users u){
		List<UserRoles> rL = u.getRoleList();
		for(UserRoles r:rL){
			if(r.getRoleType() == UserRoles.ADMIN_ROLE)
				return true;
		}
		return false;
	}
	
	public Universities getAdministeredUniv(Users u){
		List<UserRoles> rL = u.getRoleList();
		for (UserRoles r : rL) {
			if (r.getRoleType() == UserRoles.ADMIN_ROLE)
				return r.getUniversity();
		}
		return null;
	}

	public UserRoles addUser(Universities univ, Users u, int roleType,
			String uniqueId) {
		if(isUserPresent(univ, u))
			return null;
		if(isUserAdmin(u) && roleType == UserRoles.ADMIN_ROLE)
			return null;
		UserRoles role = new UserRoles();
		role.setCreationTimestamp(new Date());
		role.setRoleType(roleType);
		role.setStatus(UserRoles.STATUS_INVITED);
		role.setUniversity(univ);
		role.setUnivUniqId(uniqueId);
		role.setUser(u);
		
		getDataContext().registerNewObject(role);
		getDataContext().commitChanges();
		return role;
	}

	public boolean updateRole(Universities univ, Users u, int roleType,
			String univUniqId) {
		UserRoles r = getRole(univ, u);
		if (r == null)
			return false;
				r.setRoleType(roleType);
		r.setUnivUniqId(univUniqId);
				getDataContext().commitChanges();
				return true;
			}

	public boolean changeRole(Universities univ, Users u, int roleType) {
		return updateRole(univ, u, roleType, getRole(univ, u).getUnivUniqId());
		}
	
	public void removeUser(Universities univ, Users u){
		UserRoles deleteRole = getRole(univ, u);
		if(deleteRole != null)
			getDataContext().deleteObject(deleteRole);

		List<UnivDeptLink> udlList = univ.getDeptLinks();
		for(UnivDeptLink udl:udlList){
			if(udl.getAssociationType() == UnivDeptLink.UNIVERSITY_DEPT_OWNER){
				new UserDeptLinkDAO(ormInterface)
						.remove(udl.getDepartment(), u);
			}
		}
		getDataContext().commitChanges();
	}
	
	public List<UserRoles> getOutstandingInvites(Users u){
		List<UserRoles> ur = u.getRoleList();
		List<UserRoles> rtList = new ArrayList<UserRoles>();
		for(UserRoles x:ur){
			if(x.getStatus() == UserRoles.STATUS_INVITED)
				rtList.add(x);
		}
		return rtList;
	}
	
	public String addStudentToUniv(Universities univ, Users u, Users from,
			String univUniqId) {
		if (isUserPresent(univ, u)) {
			updateRole(univ, u, UserRoles.STUDENT_ROLE, univUniqId);
			return "Updated user information for student "
					+ u.getCompleteUserName();
		} else {
			UserRoles ur = addUser(univ, u, UserRoles.STUDENT_ROLE, univUniqId);
			if (ur != null) {
				if (u.getStatus() == Users.ACTIVE) {
					new OutgoingEmailsDAO(ormInterface)
							.sendMail(new ExistingUserInvite(u, from, univ)
									.send());
				} else {
					new OutgoingEmailsDAO(ormInterface).sendMail(new Invite(u,
							univ, UserRoles.STUDENT_ROLE, from).send());
				}
				return "Invited user " + u.getCompleteUserName()
						+ "to university " + univ.getUniversityName();
			} else {
				return "An unknown error has occured while inviting user "
						+ u.getCompleteUserName();
			}
		}
	}
	
	public String addUserFB(Universities univ, Users u, int roleType, Users from){
		if(isUserPresent(univ, u))
			return "User " + u.getCompleteUserName()
					+ " is already present in " + univ.getUniversityName();
		if(isUserAdmin(u) && roleType== UserRoles.ADMIN_ROLE)
			return "User "
					+ u.getCompleteUserName()
					+ " is a already a university administrator in a different university";
		if (addUser(univ, u, roleType, "") != null) {
			if (u.getStatus() == Users.ACTIVE) {
				new OutgoingEmailsDAO(ormInterface)
						.sendMail(new ExistingUserInvite(u, from, univ).send());
			} else {
				new OutgoingEmailsDAO(ormInterface).sendMail(new Invite(u,
						univ, roleType, from).send());
			}
			return "User " + u.getCompleteUserName() + " invited to "
					+ univ.getUniversityName();
		} else
			return "Error in adding " + u.getCompleteUserName() + " to "
					+ univ.getUniversityName();
		}

	@SuppressWarnings("unchecked")
	public Users getUserByUniqueId(String uniqueId) {
		Expression exp = Expression.fromString("univUniqId = $univUniqId");
		HashMap<String, String> hm = new HashMap<String, String>();
		hm.put("univUniqId", uniqueId);
		SelectQuery query = new SelectQuery(UserRoles.class, exp
				.expWithParameters(hm));
		List<UserRoles> ul = getDataContext().performQuery(query);
		for(UserRoles ur:ul){
			if(ur.getRoleType() == UserRoles.STUDENT_ROLE){
				return ur.getUser();
	}
}
		return null;
	}
}
